green <- miscgis::miscgis_pals$tableau_cat[["green"]]
blue <- miscgis::miscgis_pals$tableau_cat[["blue"]]
orange <- miscgis::miscgis_pals$tableau_cat[["orange"]]
red <- miscgis::miscgis_pals$tableau_cat[["red"]]
teal <- miscgis::miscgis_pals$tableau_cat[["teal"]]
pal_rgb_4 <- miscgis::miscgis_pals$tableau_cat[c("red","gold","green","blue")] %>% unlist %>% palette()
pal_rgb_4 <- miscgis::miscgis_pals$tableau_cat[c("red","gold","green","blue")] %>% unlist %>% palette()
pal_rgb_6 <- miscgis::miscgis_pals$tableau_cat[c("red","gold","green","blue","orange","purple")] %>% unlist %>% palette()
pal_rgb_6 <- miscgis::miscgis_pals$tableau_cat[c("red","gold","green","blue","orange","purple")] %>% unlist %>% palette()

Seattle Boundary

if(!file.exists(root_file('1-data/4-interim/seattle-sf.rds'))){
        tigris::places(state = "WA") %>%
                tigris::filter_place(place = "Seattle") %>%
                spTransform(CRSobj = crs_proj) %>% 
                st_as_sf() %>% 
                miscgis::coerce_to_geom(sf::st_multipolygon) %>% 
                write_rds(root_file('1-data/4-interim/seattle-sf.rds'))
        
}
sea_sf <- read_rds(root_file('1-data/4-interim/seattle-sf.rds'))
green <- miscgis::miscgis_pals$tableau_cat[["green"]]
myLfltGrey(data = as(sea_sf,'Spatial')) %>% 
        myLfltOpts() %>% 
        addPolygons(color = green,opacity = 1,fillColor = green,fillOpacity = .5)

King County Subdivision Boundary

if(!file.exists(root_file('1-data/4-interim/seattle-ccd-sf.rds'))){
        tigris::county_subdivisions(state = "53",county = "033") %>% 
                subset(NAME == "Seattle") %>% 
                spTransform(CRSobj = crs_proj) %>% 
                st_as_sf() %>% 
                miscgis::coerce_to_geom(sf::st_multipolygon) %>% 
                write_rds(root_file('1-data/4-interim/seattle-ccd-sf.rds'))
}
sea_ccd_sf <- read_rds(root_file('1-data/4-interim/seattle-ccd-sf.rds'))
myLfltGrey(data = as(sea_ccd_sf,'Spatial')) %>% 
        myLfltOpts() %>% 
        addPolygons(color = blue,opacity = 1,fillColor = blue,fillOpacity = .5)

Tracts in King County

Although this assessment is primarily focused on three communities within the Seattle CCD subdivision of King County, one of the indicators (housing market conditions) uses neighboring tracts to determine displacement risk. Some of the neighboring tracts are part of other county subdivision, but rather than targeting just those specific tracts, this method collects data for all King County tracts and then runs the analysis on the appropriate subsets.

In the absence of a straight-forward method for identifying all the census tracts in the Seattle CCD subdivision of King County, it is possible to extract this information from American Factfinder. This tutorial describes how to use the American Factfinder interface to extract a list of all “all tracts within (or partially within) a census place”; substituting “county subdivision” for “place” will retrieve the desired results.

if(!file.exists(root_file('1-data/4-interim/tr-kc-wtr-sf.rds'))){
        
        # All KC tracts
        tr_kc_wtr_sf <-
                tigris::tracts(state = '53',county = '033', year = 2014) %>%
                spTransform(CRSobj = crs_proj) %>% 
                st_as_sf() %>% 
                miscgis::coerce_to_geom(sf::st_multipolygon) 
       
         # Seattle CCD tracts 
         # Note: because this selection includes all tracts "within or partially-within" the Seattle CC,
         # several tract GEOIDs are duplicated in the selection. For the sake of clarity, these duplicates
         # are removed from the final vector of GEOIDs.
        tr_ccd_geoid <- 
                read_csv(
                        root_file('1-data/3-external/manual/seattle-ccd/ACS_12_5YR_B01001/ACS_12_5YR_B01001_with_ann.csv'), 
                        col_types = cols(Id2 = col_character()), 
                        skip = 1) %>% 
                mutate(NEW_GEOID1 = str_sub(Id2,1,5),
                       NEW_GEOID2 = str_sub(Id2,16,21),
                       GEOID = paste0(NEW_GEOID1,NEW_GEOID2),
                       UNIQUE = !duplicated(GEOID)) %>%
                filter(UNIQUE) %>% 
                select(GEOID) %>% unlist(use.names = F)
        
        # Create a county Seattle CCD subdivision column and save
        tr_kc_wtr_sf %>% 
                mutate(SEACCD_LGL = ifelse(GEOID %in% tr_ccd_geoid,TRUE,FALSE)) %>% 
                write_rds(root_file('1-data/4-interim/tr-kc-wtr-sf.rds'))
}
tr_kc_wtr_sf <- read_rds(root_file('1-data/4-interim/tr-kc-wtr-sf.rds'))
show_tr_ccd_wtr_sf <- function(){
        
        seaccd <- tr_kc_wtr_sf %>% filter(SEACCD_LGL)
        other_kc <- tr_kc_wtr_sf %>% filter(!SEACCD_LGL)
        
        myLfltGrey() %>% 
                myLfltOpts() %>% 
                addPolygons(data = as(seaccd,"Spatial"),weight = .5,color = blue,opacity = 1,fillColor = blue,fillOpacity = .5) %>% 
                addPolygons(data = as(other_kc,"Spatial"),weight = .5,color = orange,opacity = 1,fillColor = orange,fillOpacity = .5)
}
show_tr_ccd_wtr_sf()

Puget Sound Waterbodies

These are useful for “clipping” census geographies whose boundaries extend into waterbodies.

if(!file.exists(root_file('1-data/4-interim/wtr-sf.rds'))){
        fp_wtr <- root_file('1-data/3-external/NHDMajor.gdb')
# check if the file already exists, if not then download it
if(!file.exists(fp_wtr)){
        
        url <- "ftp://www.ecy.wa.gov/gis_a/inlandWaters/NHD/NHDmajor.gdb.zip" # save the URL for the waterbodies data
        
        temp <- tempfile() # create a temporary file to hold the compressed download
        
        download(url, dest = temp, mode="wb") # download the file
        
        unzip (temp, exdir = root_file('1-data/3-external/')) # extract the ESRI geodatabase file to a project folder
}
wtr_sp <-
        suppressWarnings(readOGR(dsn = fp_wtr,      # create a waterbodies shape
                layer = "NHD_MajorWaterbodies",verbose = FALSE,pointDropZ = TRUE)) %>%
        gBuffer(byid=TRUE, width=0) %>% # clean up self-intersecting polygons
        spTransform(CRSobj = crs_proj)  # transform the projection to match the project projection
wtr_sf <-  
        wtr_sp %>% 
        st_as_sf() %>% 
        miscgis::coerce_to_geom(st_multipolygon)
wtr_sf %>% 
        st_intersects(x = sea_ccd_sf,y = .) %>% 
        unlist(use.names = F) %>% 
        wtr_sf[.,] %>% 
        write_rds(root_file('1-data/4-interim/wtr-sf.rds'))
}
wtr_sf <- read_rds(root_file('1-data/4-interim/wtr-sf.rds'))
show_wtr <- function(){
        myLfltGrey(data = as(wtr_sf,'Spatial')) %>% 
                myLfltOpts() %>% 
                addPolygons(color = blue, opacity = 1, 
                            weight = .5, fillColor = blue,fillOpacity = .5)        
}
show_wtr()

KC Tracts Without (Western) Waterbodies

if(!file.exists(root_file('1-data/4-interim/tr-kc-sf.rds'))){
        tr_kc_wtr_sf %>% 
                filter(TRACTCE %!in% '990100') %>% # remove the Puget Sound tract
                mutate(geometry = st_difference(geometry,st_union(wtr_sf))) %>% 
                coerce_to_geom(st_multipolygon) %>% 
                write_rds(root_file('1-data/4-interim/tr-kc-sf.rds'))
}
tr_kc_sf <- read_rds(root_file('1-data/4-interim/tr-kc-sf.rds'))
show_tr_kc_sf <- function(){
        
        seaccd <- tr_kc_sf %>% filter(SEACCD_LGL)
        other_kc <- tr_kc_sf %>% filter(!SEACCD_LGL)
        
        myLfltGrey() %>% 
                myLfltOpts() %>% 
        addPolygons(data = as(seaccd,"Spatial"),weight = .5,color = blue,opacity = 1,fillColor = blue,fillOpacity = .5) %>% 
        addPolygons(data = as(other_kc,"Spatial"),weight = .5,color = orange,opacity = 1,fillColor = orange,fillOpacity = .5)
}
show_tr_kc_sf()

King County Without (Western) Waterbodies

if(!file.exists(root_file('1-data/4-interim/kc-sf.rds'))){
        tigris::counties(state = '53', cb = TRUE) %>% 
                st_as_sf() %>% 
                st_transform(crs_proj@projargs) %>% 
                filter(NAME %in% 'King') %>% 
                miscgis::coerce_to_geom(sf::st_multipolygon) %>% 
                mutate(geometry = st_difference(geometry,st_union(wtr_sf))) %>% 
                write_rds(root_file('1-data/4-interim/kc-sf.rds'))
        
}
kc_sf <- read_rds(root_file('1-data/4-interim/kc-sf.rds'))
LS0tCmRmX3ByaW50OiB0aWJibGUKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICBwZGZfZG9jdW1lbnQ6CiAgICBrZWVwX3RleDogeWVzCmFsd2F5c19hbGxvd19odG1sOiB5ZXMKLS0tCgpgYGB7ciBtaXNjLXNldHVwLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxjb21tZW50PUZBTFNFfQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KG9wZXJhdG9yLnRvb2xzKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHJwcm9qcm9vdCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmdkYWwpCmxpYnJhcnkoc3ApCmxpYnJhcnkocmdlb3MpCmxpYnJhcnkobWlzY2dpcykKbGlicmFyeSh0aWdyaXMpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KGRvd25sb2FkZXIpCmxpYnJhcnkobWlzY2dpcykKbGlicmFyeShzZikKcm9vdCA8LSBycHJvanJvb3Q6OmlzX3JzdHVkaW9fcHJvamVjdApyb290X2ZpbGUgPC0gcm9vdCRtYWtlX2ZpeF9maWxlKCkKYGBgCgpgYGB7ciBtaXNjLWNvbG9yc30KZ3JlZW4gPC0gbWlzY2dpczo6bWlzY2dpc19wYWxzJHRhYmxlYXVfY2F0W1siZ3JlZW4iXV0KYmx1ZSA8LSBtaXNjZ2lzOjptaXNjZ2lzX3BhbHMkdGFibGVhdV9jYXRbWyJibHVlIl1dCm9yYW5nZSA8LSBtaXNjZ2lzOjptaXNjZ2lzX3BhbHMkdGFibGVhdV9jYXRbWyJvcmFuZ2UiXV0KcmVkIDwtIG1pc2NnaXM6Om1pc2NnaXNfcGFscyR0YWJsZWF1X2NhdFtbInJlZCJdXQp0ZWFsIDwtIG1pc2NnaXM6Om1pc2NnaXNfcGFscyR0YWJsZWF1X2NhdFtbInRlYWwiXV0KcGFsX3JnYl80IDwtIG1pc2NnaXM6Om1pc2NnaXNfcGFscyR0YWJsZWF1X2NhdFtjKCJyZWQiLCJnb2xkIiwiZ3JlZW4iLCJibHVlIildICU+JSB1bmxpc3QgJT4lIHBhbGV0dGUoKQpwYWxfcmdiXzQgPC0gbWlzY2dpczo6bWlzY2dpc19wYWxzJHRhYmxlYXVfY2F0W2MoInJlZCIsImdvbGQiLCJncmVlbiIsImJsdWUiKV0gJT4lIHVubGlzdCAlPiUgcGFsZXR0ZSgpCnBhbF9yZ2JfNiA8LSBtaXNjZ2lzOjptaXNjZ2lzX3BhbHMkdGFibGVhdV9jYXRbYygicmVkIiwiZ29sZCIsImdyZWVuIiwiYmx1ZSIsIm9yYW5nZSIsInB1cnBsZSIpXSAlPiUgdW5saXN0ICU+JSBwYWxldHRlKCkKcGFsX3JnYl82IDwtIG1pc2NnaXM6Om1pc2NnaXNfcGFscyR0YWJsZWF1X2NhdFtjKCJyZWQiLCJnb2xkIiwiZ3JlZW4iLCJibHVlIiwib3JhbmdlIiwicHVycGxlIildICU+JSB1bmxpc3QgJT4lIHBhbGV0dGUoKQpgYGAKCiMjI1NlYXR0bGUgQm91bmRhcnkKCmBgYHtyIG1pc2Mtc2VhLWJvdW5kLCBmaWcuY2FwPSJTZWF0dGxlXCdzIGdlb2dyYXBoaWMgYm91bmRhcnkifQoKaWYoIWZpbGUuZXhpc3RzKHJvb3RfZmlsZSgnMS1kYXRhLzQtaW50ZXJpbS9zZWF0dGxlLXNmLnJkcycpKSl7CiAgICAgICAgdGlncmlzOjpwbGFjZXMoc3RhdGUgPSAiV0EiKSAlPiUKICAgICAgICAgICAgICAgIHRpZ3Jpczo6ZmlsdGVyX3BsYWNlKHBsYWNlID0gIlNlYXR0bGUiKSAlPiUKICAgICAgICAgICAgICAgIHNwVHJhbnNmb3JtKENSU29iaiA9IGNyc19wcm9qKSAlPiUgCiAgICAgICAgICAgICAgICBzdF9hc19zZigpICU+JSAKICAgICAgICAgICAgICAgIG1pc2NnaXM6OmNvZXJjZV90b19nZW9tKHNmOjpzdF9tdWx0aXBvbHlnb24pICU+JSAKICAgICAgICAgICAgICAgIHdyaXRlX3Jkcyhyb290X2ZpbGUoJzEtZGF0YS80LWludGVyaW0vc2VhdHRsZS1zZi5yZHMnKSkKICAgICAgICAKfQoKc2VhX3NmIDwtIHJlYWRfcmRzKHJvb3RfZmlsZSgnMS1kYXRhLzQtaW50ZXJpbS9zZWF0dGxlLXNmLnJkcycpKQoKZ3JlZW4gPC0gbWlzY2dpczo6bWlzY2dpc19wYWxzJHRhYmxlYXVfY2F0W1siZ3JlZW4iXV0KCm15TGZsdEdyZXkoZGF0YSA9IGFzKHNlYV9zZiwnU3BhdGlhbCcpKSAlPiUgCiAgICAgICAgbXlMZmx0T3B0cygpICU+JSAKICAgICAgICBhZGRQb2x5Z29ucyhjb2xvciA9IGdyZWVuLG9wYWNpdHkgPSAxLGZpbGxDb2xvciA9IGdyZWVuLGZpbGxPcGFjaXR5ID0gLjUpCgpgYGAKCiMjI0tpbmcgQ291bnR5IFN1YmRpdmlzaW9uIEJvdW5kYXJ5CgpgYGB7ciBtaXNjLXNlYS1jY2QsIGZpZy5jYXA9IlNlYXR0bGUgU3ViZGl2aXNpb24gb2YgS2luZyBDb3VudHlcJ3MgZ2VvZ3JhcGhpYyBib3VuZGFyeSJ9CgppZighZmlsZS5leGlzdHMocm9vdF9maWxlKCcxLWRhdGEvNC1pbnRlcmltL3NlYXR0bGUtY2NkLXNmLnJkcycpKSl7CiAgICAgICAgdGlncmlzOjpjb3VudHlfc3ViZGl2aXNpb25zKHN0YXRlID0gIjUzIixjb3VudHkgPSAiMDMzIikgJT4lIAogICAgICAgICAgICAgICAgc3Vic2V0KE5BTUUgPT0gIlNlYXR0bGUiKSAlPiUgCiAgICAgICAgICAgICAgICBzcFRyYW5zZm9ybShDUlNvYmogPSBjcnNfcHJvaikgJT4lIAogICAgICAgICAgICAgICAgc3RfYXNfc2YoKSAlPiUgCiAgICAgICAgICAgICAgICBtaXNjZ2lzOjpjb2VyY2VfdG9fZ2VvbShzZjo6c3RfbXVsdGlwb2x5Z29uKSAlPiUgCiAgICAgICAgICAgICAgICB3cml0ZV9yZHMocm9vdF9maWxlKCcxLWRhdGEvNC1pbnRlcmltL3NlYXR0bGUtY2NkLXNmLnJkcycpKQp9CgpzZWFfY2NkX3NmIDwtIHJlYWRfcmRzKHJvb3RfZmlsZSgnMS1kYXRhLzQtaW50ZXJpbS9zZWF0dGxlLWNjZC1zZi5yZHMnKSkKCm15TGZsdEdyZXkoZGF0YSA9IGFzKHNlYV9jY2Rfc2YsJ1NwYXRpYWwnKSkgJT4lIAogICAgICAgIG15TGZsdE9wdHMoKSAlPiUgCiAgICAgICAgYWRkUG9seWdvbnMoY29sb3IgPSBibHVlLG9wYWNpdHkgPSAxLGZpbGxDb2xvciA9IGJsdWUsZmlsbE9wYWNpdHkgPSAuNSkKCmBgYAoKIyMjIFRyYWN0cyBpbiBLaW5nIENvdW50eQpBbHRob3VnaCB0aGlzIGFzc2Vzc21lbnQgaXMgcHJpbWFyaWx5IGZvY3VzZWQgb24gdGhyZWUgY29tbXVuaXRpZXMgd2l0aGluIHRoZSBTZWF0dGxlIENDRCBzdWJkaXZpc2lvbiBvZiBLaW5nIENvdW50eSwgb25lIG9mIHRoZSBpbmRpY2F0b3JzIChob3VzaW5nIG1hcmtldCBjb25kaXRpb25zKSB1c2VzIG5laWdoYm9yaW5nIHRyYWN0cyB0byBkZXRlcm1pbmUgZGlzcGxhY2VtZW50IHJpc2suIFNvbWUgb2YgdGhlIG5laWdoYm9yaW5nIHRyYWN0cyBhcmUgcGFydCBvZiBvdGhlciBjb3VudHkgc3ViZGl2aXNpb24sIGJ1dCByYXRoZXIgdGhhbiB0YXJnZXRpbmcganVzdCB0aG9zZSBzcGVjaWZpYyB0cmFjdHMsIHRoaXMgbWV0aG9kIGNvbGxlY3RzIGRhdGEgZm9yIGFsbCBLaW5nIENvdW50eSB0cmFjdHMgYW5kIHRoZW4gcnVucyB0aGUgYW5hbHlzaXMgb24gdGhlIGFwcHJvcHJpYXRlIHN1YnNldHMuCgpJbiB0aGUgYWJzZW5jZSBvZiBhIHN0cmFpZ2h0LWZvcndhcmQgbWV0aG9kIGZvciBpZGVudGlmeWluZyBhbGwgdGhlIGNlbnN1cyB0cmFjdHMgaW4gdGhlIFNlYXR0bGUgQ0NEIHN1YmRpdmlzaW9uIG9mIEtpbmcgQ291bnR5LCBpdCBpcyBwb3NzaWJsZSB0byBleHRyYWN0IHRoaXMgaW5mb3JtYXRpb24gZnJvbSBbQW1lcmljYW4gRmFjdGZpbmRlcl0oaHR0cHM6Ly9mYWN0ZmluZGVyLmNlbnN1cy5nb3YvZmFjZXMvbmF2L2pzZi9wYWdlcy9pbmRleC54aHRtbCkuIFRoaXMgW3R1dG9yaWFsXShodHRwczovL2Fzay5jZW5zdXMuZ292L2ZhcS5waHA/aWQ9NTAwMCZmYXFJZD0xNjA1KSBkZXNjcmliZXMgaG93IHRvIHVzZSB0aGUgQW1lcmljYW4gRmFjdGZpbmRlciBpbnRlcmZhY2UgdG8gZXh0cmFjdCBhIGxpc3Qgb2YgYWxsICJhbGwgdHJhY3RzIHdpdGhpbiAob3IgcGFydGlhbGx5IHdpdGhpbikgYSBjZW5zdXMgcGxhY2UiOyBzdWJzdGl0dXRpbmcgImNvdW50eSBzdWJkaXZpc2lvbiIgZm9yICJwbGFjZSIgd2lsbCByZXRyaWV2ZSB0aGUgZGVzaXJlZCByZXN1bHRzLgoKYGBge3IgbWlzYy10ci1rYy13dHJ9CgppZighZmlsZS5leGlzdHMocm9vdF9maWxlKCcxLWRhdGEvNC1pbnRlcmltL3RyLWtjLXd0ci1zZi5yZHMnKSkpewogICAgICAgIAogICAgICAgICMgQWxsIEtDIHRyYWN0cwogICAgICAgIHRyX2tjX3d0cl9zZiA8LQogICAgICAgICAgICAgICAgdGlncmlzOjp0cmFjdHMoc3RhdGUgPSAnNTMnLGNvdW50eSA9ICcwMzMnLCB5ZWFyID0gMjAxNCkgJT4lCiAgICAgICAgICAgICAgICBzcFRyYW5zZm9ybShDUlNvYmogPSBjcnNfcHJvaikgJT4lIAogICAgICAgICAgICAgICAgc3RfYXNfc2YoKSAlPiUgCiAgICAgICAgICAgICAgICBtaXNjZ2lzOjpjb2VyY2VfdG9fZ2VvbShzZjo6c3RfbXVsdGlwb2x5Z29uKSAKICAgICAgIAogICAgICAgICAjIFNlYXR0bGUgQ0NEIHRyYWN0cyAKICAgICAgICAgIyBOb3RlOiBiZWNhdXNlIHRoaXMgc2VsZWN0aW9uIGluY2x1ZGVzIGFsbCB0cmFjdHMgIndpdGhpbiBvciBwYXJ0aWFsbHktd2l0aGluIiB0aGUgU2VhdHRsZSBDQywKICAgICAgICAgIyBzZXZlcmFsIHRyYWN0IEdFT0lEcyBhcmUgZHVwbGljYXRlZCBpbiB0aGUgc2VsZWN0aW9uLiBGb3IgdGhlIHNha2Ugb2YgY2xhcml0eSwgdGhlc2UgZHVwbGljYXRlcwogICAgICAgICAjIGFyZSByZW1vdmVkIGZyb20gdGhlIGZpbmFsIHZlY3RvciBvZiBHRU9JRHMuCiAgICAgICAgdHJfY2NkX2dlb2lkIDwtIAogICAgICAgICAgICAgICAgcmVhZF9jc3YoCiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RfZmlsZSgnMS1kYXRhLzMtZXh0ZXJuYWwvbWFudWFsL3NlYXR0bGUtY2NkL0FDU18xMl81WVJfQjAxMDAxL0FDU18xMl81WVJfQjAxMDAxX3dpdGhfYW5uLmNzdicpLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29sX3R5cGVzID0gY29scyhJZDIgPSBjb2xfY2hhcmFjdGVyKCkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgc2tpcCA9IDEpICU+JSAKICAgICAgICAgICAgICAgIG11dGF0ZShORVdfR0VPSUQxID0gc3RyX3N1YihJZDIsMSw1KSwKICAgICAgICAgICAgICAgICAgICAgICBORVdfR0VPSUQyID0gc3RyX3N1YihJZDIsMTYsMjEpLAogICAgICAgICAgICAgICAgICAgICAgIEdFT0lEID0gcGFzdGUwKE5FV19HRU9JRDEsTkVXX0dFT0lEMiksCiAgICAgICAgICAgICAgICAgICAgICAgVU5JUVVFID0gIWR1cGxpY2F0ZWQoR0VPSUQpKSAlPiUKICAgICAgICAgICAgICAgIGZpbHRlcihVTklRVUUpICU+JSAKICAgICAgICAgICAgICAgIHNlbGVjdChHRU9JRCkgJT4lIHVubGlzdCh1c2UubmFtZXMgPSBGKQogICAgICAgIAogICAgICAgICMgQ3JlYXRlIGEgY291bnR5IFNlYXR0bGUgQ0NEIHN1YmRpdmlzaW9uIGNvbHVtbiBhbmQgc2F2ZQoKICAgICAgICB0cl9rY193dHJfc2YgJT4lIAogICAgICAgICAgICAgICAgbXV0YXRlKFNFQUNDRF9MR0wgPSBpZmVsc2UoR0VPSUQgJWluJSB0cl9jY2RfZ2VvaWQsVFJVRSxGQUxTRSkpICU+JSAKICAgICAgICAgICAgICAgIHdyaXRlX3Jkcyhyb290X2ZpbGUoJzEtZGF0YS80LWludGVyaW0vdHIta2Mtd3RyLXNmLnJkcycpKQp9Cgp0cl9rY193dHJfc2YgPC0gcmVhZF9yZHMocm9vdF9maWxlKCcxLWRhdGEvNC1pbnRlcmltL3RyLWtjLXd0ci1zZi5yZHMnKSkKCnNob3dfdHJfY2NkX3d0cl9zZiA8LSBmdW5jdGlvbigpewogICAgICAgIAogICAgICAgIHNlYWNjZCA8LSB0cl9rY193dHJfc2YgJT4lIGZpbHRlcihTRUFDQ0RfTEdMKQogICAgICAgIG90aGVyX2tjIDwtIHRyX2tjX3d0cl9zZiAlPiUgZmlsdGVyKCFTRUFDQ0RfTEdMKQogICAgICAgIAogICAgICAgIG15TGZsdEdyZXkoKSAlPiUgCiAgICAgICAgICAgICAgICBteUxmbHRPcHRzKCkgJT4lIAogICAgICAgICAgICAgICAgYWRkUG9seWdvbnMoZGF0YSA9IGFzKHNlYWNjZCwiU3BhdGlhbCIpLHdlaWdodCA9IC41LGNvbG9yID0gYmx1ZSxvcGFjaXR5ID0gMSxmaWxsQ29sb3IgPSBibHVlLGZpbGxPcGFjaXR5ID0gLjUpICU+JSAKICAgICAgICAgICAgICAgIGFkZFBvbHlnb25zKGRhdGEgPSBhcyhvdGhlcl9rYywiU3BhdGlhbCIpLHdlaWdodCA9IC41LGNvbG9yID0gb3JhbmdlLG9wYWNpdHkgPSAxLGZpbGxDb2xvciA9IG9yYW5nZSxmaWxsT3BhY2l0eSA9IC41KQp9CgpzaG93X3RyX2NjZF93dHJfc2YoKQoKCmBgYAoKIyMjUHVnZXQgU291bmQgV2F0ZXJib2RpZXMKClRoZXNlIGFyZSB1c2VmdWwgZm9yICJjbGlwcGluZyIgY2Vuc3VzIGdlb2dyYXBoaWVzIHdob3NlIGJvdW5kYXJpZXMgZXh0ZW5kIGludG8gd2F0ZXJib2RpZXMuCgpgYGB7ciBtaXNjLXd0ciwgZmlnLmNhcD0iUHVnZXQgU291bmQgd2F0ZXJib2RpZXMifQoKaWYoIWZpbGUuZXhpc3RzKHJvb3RfZmlsZSgnMS1kYXRhLzQtaW50ZXJpbS93dHItc2YucmRzJykpKXsKICAgICAgICBmcF93dHIgPC0gcm9vdF9maWxlKCcxLWRhdGEvMy1leHRlcm5hbC9OSERNYWpvci5nZGInKQoKIyBjaGVjayBpZiB0aGUgZmlsZSBhbHJlYWR5IGV4aXN0cywgaWYgbm90IHRoZW4gZG93bmxvYWQgaXQKaWYoIWZpbGUuZXhpc3RzKGZwX3d0cikpewogICAgICAgIAogICAgICAgIHVybCA8LSAiZnRwOi8vd3d3LmVjeS53YS5nb3YvZ2lzX2EvaW5sYW5kV2F0ZXJzL05IRC9OSERtYWpvci5nZGIuemlwIiAjIHNhdmUgdGhlIFVSTCBmb3IgdGhlIHdhdGVyYm9kaWVzIGRhdGEKICAgICAgICAKICAgICAgICB0ZW1wIDwtIHRlbXBmaWxlKCkgIyBjcmVhdGUgYSB0ZW1wb3JhcnkgZmlsZSB0byBob2xkIHRoZSBjb21wcmVzc2VkIGRvd25sb2FkCiAgICAgICAgCiAgICAgICAgZG93bmxvYWQodXJsLCBkZXN0ID0gdGVtcCwgbW9kZT0id2IiKSAjIGRvd25sb2FkIHRoZSBmaWxlCiAgICAgICAgCiAgICAgICAgdW56aXAgKHRlbXAsIGV4ZGlyID0gcm9vdF9maWxlKCcxLWRhdGEvMy1leHRlcm5hbC8nKSkgIyBleHRyYWN0IHRoZSBFU1JJIGdlb2RhdGFiYXNlIGZpbGUgdG8gYSBwcm9qZWN0IGZvbGRlcgp9Cgp3dHJfc3AgPC0KICAgICAgICBzdXBwcmVzc1dhcm5pbmdzKHJlYWRPR1IoZHNuID0gZnBfd3RyLCAgICAgICMgY3JlYXRlIGEgd2F0ZXJib2RpZXMgc2hhcGUKICAgICAgICAgICAgICAgIGxheWVyID0gIk5IRF9NYWpvcldhdGVyYm9kaWVzIix2ZXJib3NlID0gRkFMU0UscG9pbnREcm9wWiA9IFRSVUUpKSAlPiUKICAgICAgICBnQnVmZmVyKGJ5aWQ9VFJVRSwgd2lkdGg9MCkgJT4lICMgY2xlYW4gdXAgc2VsZi1pbnRlcnNlY3RpbmcgcG9seWdvbnMKICAgICAgICBzcFRyYW5zZm9ybShDUlNvYmogPSBjcnNfcHJvaikgICMgdHJhbnNmb3JtIHRoZSBwcm9qZWN0aW9uIHRvIG1hdGNoIHRoZSBwcm9qZWN0IHByb2plY3Rpb24Kd3RyX3NmIDwtICAKICAgICAgICB3dHJfc3AgJT4lIAogICAgICAgIHN0X2FzX3NmKCkgJT4lIAogICAgICAgIG1pc2NnaXM6OmNvZXJjZV90b19nZW9tKHN0X211bHRpcG9seWdvbikKCnd0cl9zZiAlPiUgCiAgICAgICAgc3RfaW50ZXJzZWN0cyh4ID0gc2VhX2NjZF9zZix5ID0gLikgJT4lIAogICAgICAgIHVubGlzdCh1c2UubmFtZXMgPSBGKSAlPiUgCiAgICAgICAgd3RyX3NmWy4sXSAlPiUgCiAgICAgICAgd3JpdGVfcmRzKHJvb3RfZmlsZSgnMS1kYXRhLzQtaW50ZXJpbS93dHItc2YucmRzJykpCn0KCnd0cl9zZiA8LSByZWFkX3Jkcyhyb290X2ZpbGUoJzEtZGF0YS80LWludGVyaW0vd3RyLXNmLnJkcycpKQoKc2hvd193dHIgPC0gZnVuY3Rpb24oKXsKICAgICAgICBteUxmbHRHcmV5KGRhdGEgPSBhcyh3dHJfc2YsJ1NwYXRpYWwnKSkgJT4lIAogICAgICAgICAgICAgICAgbXlMZmx0T3B0cygpICU+JSAKICAgICAgICAgICAgICAgIGFkZFBvbHlnb25zKGNvbG9yID0gYmx1ZSwgb3BhY2l0eSA9IDEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VpZ2h0ID0gLjUsIGZpbGxDb2xvciA9IGJsdWUsZmlsbE9wYWNpdHkgPSAuNSkgICAgICAgIAp9CgpzaG93X3d0cigpCgpgYGAKCiMjIyBLQyBUcmFjdHMgV2l0aG91dCAoV2VzdGVybikgV2F0ZXJib2RpZXMgCmBgYHtyIG1pc2MtdHJhY3RzLWNjZC1uby13dHJ9CgppZighZmlsZS5leGlzdHMocm9vdF9maWxlKCcxLWRhdGEvNC1pbnRlcmltL3RyLWtjLXNmLnJkcycpKSl7CiAgICAgICAgdHJfa2Nfd3RyX3NmICU+JSAKICAgICAgICAgICAgICAgIGZpbHRlcihUUkFDVENFICUhaW4lICc5OTAxMDAnKSAlPiUgIyByZW1vdmUgdGhlIFB1Z2V0IFNvdW5kIHRyYWN0CiAgICAgICAgICAgICAgICBtdXRhdGUoZ2VvbWV0cnkgPSBzdF9kaWZmZXJlbmNlKGdlb21ldHJ5LHN0X3VuaW9uKHd0cl9zZikpKSAlPiUgCiAgICAgICAgICAgICAgICBjb2VyY2VfdG9fZ2VvbShzdF9tdWx0aXBvbHlnb24pICU+JSAKICAgICAgICAgICAgICAgIHdyaXRlX3Jkcyhyb290X2ZpbGUoJzEtZGF0YS80LWludGVyaW0vdHIta2Mtc2YucmRzJykpCn0KCnRyX2tjX3NmIDwtIHJlYWRfcmRzKHJvb3RfZmlsZSgnMS1kYXRhLzQtaW50ZXJpbS90ci1rYy1zZi5yZHMnKSkKCnNob3dfdHJfa2Nfc2YgPC0gZnVuY3Rpb24oKXsKICAgICAgICAKICAgICAgICBzZWFjY2QgPC0gdHJfa2Nfc2YgJT4lIGZpbHRlcihTRUFDQ0RfTEdMKQogICAgICAgIG90aGVyX2tjIDwtIHRyX2tjX3NmICU+JSBmaWx0ZXIoIVNFQUNDRF9MR0wpCiAgICAgICAgCiAgICAgICAgbXlMZmx0R3JleSgpICU+JSAKICAgICAgICAgICAgICAgIG15TGZsdE9wdHMoKSAlPiUgCiAgICAgICAgYWRkUG9seWdvbnMoZGF0YSA9IGFzKHNlYWNjZCwiU3BhdGlhbCIpLHdlaWdodCA9IC41LGNvbG9yID0gYmx1ZSxvcGFjaXR5ID0gMSxmaWxsQ29sb3IgPSBibHVlLGZpbGxPcGFjaXR5ID0gLjUpICU+JSAKICAgICAgICBhZGRQb2x5Z29ucyhkYXRhID0gYXMob3RoZXJfa2MsIlNwYXRpYWwiKSx3ZWlnaHQgPSAuNSxjb2xvciA9IG9yYW5nZSxvcGFjaXR5ID0gMSxmaWxsQ29sb3IgPSBvcmFuZ2UsZmlsbE9wYWNpdHkgPSAuNSkKfQoKc2hvd190cl9rY19zZigpCgoKCmBgYAoKIyMjIEtpbmcgQ291bnR5IFdpdGhvdXQgKFdlc3Rlcm4pIFdhdGVyYm9kaWVzCgpgYGB7ciBtaXNjLWtjfQoKaWYoIWZpbGUuZXhpc3RzKHJvb3RfZmlsZSgnMS1kYXRhLzQtaW50ZXJpbS9rYy1zZi5yZHMnKSkpewogICAgICAgIHRpZ3Jpczo6Y291bnRpZXMoc3RhdGUgPSAnNTMnLCBjYiA9IFRSVUUpICU+JSAKICAgICAgICAgICAgICAgIHN0X2FzX3NmKCkgJT4lIAogICAgICAgICAgICAgICAgc3RfdHJhbnNmb3JtKGNyc19wcm9qQHByb2phcmdzKSAlPiUgCiAgICAgICAgICAgICAgICBmaWx0ZXIoTkFNRSAlaW4lICdLaW5nJykgJT4lIAogICAgICAgICAgICAgICAgbWlzY2dpczo6Y29lcmNlX3RvX2dlb20oc2Y6OnN0X211bHRpcG9seWdvbikgJT4lIAogICAgICAgICAgICAgICAgbXV0YXRlKGdlb21ldHJ5ID0gc3RfZGlmZmVyZW5jZShnZW9tZXRyeSxzdF91bmlvbih3dHJfc2YpKSkgJT4lIAogICAgICAgICAgICAgICAgd3JpdGVfcmRzKHJvb3RfZmlsZSgnMS1kYXRhLzQtaW50ZXJpbS9rYy1zZi5yZHMnKSkKICAgICAgICAKfQoKa2Nfc2YgPC0gcmVhZF9yZHMocm9vdF9maWxlKCcxLWRhdGEvNC1pbnRlcmltL2tjLXNmLnJkcycpKQoKCmBgYAoK